
#ifndef __avmplus_avmgc_hpp__
#define __avmplus_avmgc_hpp__

#include "avmrt.h"

namespace avmgc
{
	template<class T, bool checkMissingWB=true>
    class RCPtr
    {
	public:
		RCPtr(T _t) : t(_t)
        {
			::avm_gc_incrementRef( t );
        }
        ~RCPtr()
        {
            ::avm_gc_decrementRef( t );

            t = NULL;
        }

        T operator=(T tNew)
        {
            ::avm_gc_decrementRef( t );

            t = tNew;
            
			::avm_gc_incrementRef( t );

            // this cast is safe b/c other wise compilation would fail
            return (T) t;
        }

	private:
        // Hidden and meant not to be used at all.
        RCPtr(const RCPtr<T>& other);

        inline bool valid() { return (uintptr_t)t > 1; }
        T t;
	};

	#define DRC(_type) avmgc::RCPtr< _type, true >

	template<class T> class WriteBarrier
    {
    private:
        // Always pay for a single real function call; then inline & optimize massively in WriteBarrier()
        T set(const T tNew)
        {
			::avm_gc_writeBarrier(&t, (const void*)tNew);    // updates 't'



            return tNew;
        }
    public:
        explicit WriteBarrier() : t(0)
        {
        }

        explicit WriteBarrier(T _t)
        {
            set(_t);
        }

        inline ~WriteBarrier()
        {
            t = 0;
        }

        T operator=(const WriteBarrier<T>& wb)
        {
            return set(wb.t);
        }

        T operator=(T tNew)
        {
            return set(tNew);
        }

        // BEHOLD ... The weird power of C++ operator overloading
        operator T() const { return t; }

        // let us peek at it without a cast
        T value() const { return t; }

 

        bool operator!=(T other) const { return other != t; }

        T operator->() const
        {
            return t;
        }

    private:
        // Private constructor to prevent its use and someone adding it, GCC creates
        // WriteBarriers on the stack with it
        WriteBarrier(const WriteBarrier<T>& toCopy);    // unimplemented

        T t;
    };

	#define DWB(type) avmgc::WriteBarrier< type >

	template<class T> class WriteBarrierRC
    {
    private:
        // Always pay for a single real function call; then inline & optimize massively in WriteBarrierRC()
        inline T set(const T tNew)
        {
            avm_gc_writeBarrierRC(&t, (const void*)tNew);  // updates 't'
            return tNew;
        }

    public:
        explicit WriteBarrierRC() : t(0)
        {
        }

        explicit inline WriteBarrierRC(const T _t) // : t(0) -- not necessary, WriteBarrierRC_ctor handles it
        {
            avm_gc_writeBarrierRC_ctor(&t, (const void*)_t);
        }

        inline ~WriteBarrierRC()
        {
            avm_gc_writeBarrierRC_dtor(&t);
        }

        inline T operator=(const WriteBarrierRC<T>& wb)
        {
            return set(wb.t);
        }

        inline T operator=(T tNew)
        {
            return set(tNew);
        }

        inline T value() const { return t; }

        inline operator T() const { return t; }



        inline bool operator!=(T other) const { return other != t; }

        inline T operator->() const
        {
            return t;
        }

        // Clear() clears the smart pointer without decrementing the reference count of any object stored in
        // the smart pointer.  It is essentially useful in situations where the caller has already deleted
        // the object and needs to ensure that the destruction of the smart pointer does not access the
        // deleted storage.

        inline void Clear() { t = 0; }

    private:
        // Private constructor to prevent its use and someone adding it, GCC creates
        // WriteBarrierRCs on the stack with it
        WriteBarrierRC(const WriteBarrierRC<T>& toCopy);

        T t;
    };


	#define DRCWB(type) avmgc::WriteBarrierRC< type >

	class AtomWB 
    {
    public:
		explicit AtomWB() : m_atom( 0 )
        {
            // nothing
        }

        explicit AtomWB(Atom t)  // : AtomWBCore(t) -- not necessary, atomWriteBarrier_ctor handles it
        {
			::avm_atomWriteBarrier_ctor(&m_atom, t);
        }

        ~AtomWB()
        {
			::avm_atomWriteBarrier_dtor(&m_atom);
        }

        Atom operator=(Atom tNew)
        {
         
            set(tNew);
            return tNew;
        }

        inline operator const Atom&() const { return m_atom; }
        
    private:
        explicit AtomWB(const AtomWB& toCopy); // unimplemented
        void operator=(const AtomWB& wb); // unimplemented

        Atom set(Atom atomNew)
        {
            if (m_atom != atomNew)
            {
				::avm_atomWriteBarrier( &m_atom, atomNew );
            }
            return atomNew;
        }

		Atom m_atom;
    };

	#define WBATOM avmgc::AtomWB


}
	

#endif